#include "stdafx.h"
#include "BallGameView.h"

#include <ctime>

#include "GlobalAppData.h"

#include "Camera.h"
#include "Scene.h"
#include "Node.h"

#include "SceneLoader.h"
#include "WorldData.h"

#include "DeferredPipeline.h"

#include "Graphics.h"
#include "RenderingSystem.h"
#include "MeshInstance.h"
#include "Material.h"
#include "Light.h"
#include "LoadTexture.h"

#include "PhysicsSystem.h"

//debug
#include "CollisionData.h"
#include "CollisionDetection.h"
#include "PhysicsPrimitives.h"

//gui
#include "Window.h"
#include "OnOffButton.h"

#include "RenderSettingsGui.h"

#include "GameScene.h"
#include "Ball.h"

using namespace ball;

void BallGameView::init( GameScene * scene, mgfx::RenderingSystem * rendSys, mphys::PhysicsSystem * physSys )
{
	View::load();

	mTotalTime = 0.0f;

	mScene = scene;
	mRenderSystem = rendSys;
	mPhysicsSystem = physSys;

	float screenAspect = (float)mcore::GlobalAppData::Instance.ScreenWidth / (float)mcore::GlobalAppData::Instance.ScreenHeight;
	mCamera = &mScene->getCamera();
	//mCamera->walk(-230);
	mCamera->setLens(0.25f * PI, screenAspect, 5.0f, 15000.0f);
	mRenderSystem->setProjMatrix(mCamera->proj());

	initGui();
}


void BallGameView::unload()
{
	SAFE_DELETE(mRenderSettingsGui);

	SAFE_DELETE(mScene);
	SAFE_DELETE(mPhysicsSystem);
	SAFE_DELETE(mRenderSystem);

	View::unload();
}

void BallGameView::update(float dt)
{ 
	static float SMALL_DT = 0.0001f;
	if(mTotalTime == 0.0f)
		dt = SMALL_DT;
	mTotalTime += dt;

	mPhysicsSystem->update(dt);
	
	mScene->gameUpdate(dt);
	mRenderSystem->update(dt);

	XMFLOAT3 camPos = XMFLOAT3(0.0f, 50.0f, mScene->PlayerBall->Position.z - 100.0f);
	mCamera->setPosition(camPos);

	mCamera->resetOrientation();
	mCamera->pitch(PI / 16);
	mCamera->rebuildView();
}

void BallGameView::draw()
{
	mRenderSystem->setViewMatrix(mCamera->view());
	mRenderSystem->setEyePosition(mCamera->position());
	mRenderSystem->setViewFrustum(mCamera->Frustum_);
	mgfx::DeferredPipeline::get().render(mRenderSystem->Data, mRenderSystem->Settings);

	mGui->draw();
}

bool BallGameView::onWindowMessage(UINT msg, WPARAM wParam, LPARAM lParam)
{

	sendInputToGUI(msg, wParam, lParam);

	switch( msg )
	{
	case WM_MOUSEMOVE:
		{
			static bool firstTime = true;
			int mousePosX = LOWORD(lParam);
			int mousePosY = HIWORD(lParam);
			if(firstTime)
			{
				firstTime = false;
			}
			else
			{
				int diffY = mPrevMousePosY - mousePosY;
				int diffX = mPrevMousePosX - mousePosX;
				if(diffY != 0 || diffX != 0)
				{
					mScene->mouseMove(diffX, diffY);
				}
				
			}
			mPrevMousePosX = mousePosX;
			mPrevMousePosY = mousePosY;
			return true;
		}
		break;

	case WM_LBUTTONDOWN:
		{

		}
		break;

	case WM_LBUTTONUP:
		{

		}
		break;

	case WM_KEYDOWN:
		{

			return mScene->keyEvent(util::KEY_DOWN, wParam, lParam);
		}
		break;

	case WM_KEYUP:
		{
			return mScene->keyEvent(util::KEY_UP, wParam, lParam);
		}
		break;
	}
	return false;
}

void BallGameView::initGui()
{
	mRenderSettingsGui = new medit::RenderSettingsGui(&mRenderSystem->Settings);
	mGui->addChild(*mRenderSettingsGui->GuiWindow);

	//mgui::Window * window = new mgui::Window(mgui::Rect(20, 50, 250, 500), "Render settings");
	//mGui->addChild(window);

	//mgui::OnOffButton * button = new mgui::OnOffButton(mgui::Rect(20, 50, 120, 25), "button");
	//window->addChild(button);

	//button->addListener(mgui::OnOffButton::EVENT_STATE_CHANGED, std::bind(&GameView::receiveButtonChange, this, std::placeholders::_1));
}
